﻿

#region Using Statements

using UnityEngine;
using System.Collections.Generic;

#endregion


/// <summary>
/// 
/// </summary>
public class LookAt : MonoBehaviour
{

    #region Members

    /// <summary>
    /// Target to look at.
    /// </summary>
    public Transform target;


    /// <summary>
    /// Percentage of difference between rotation and target rotation covered each second.
    /// </summary>
    public float exponentialLookRate = 0.8f;


    /// <summary>
    /// Rate in degrees per second that the object's rotation looks towards target.
    /// </summary>
    public float linearLookRate = 0.0f;


    /// <summary>
    /// Global offset from target at which to look.
    /// </summary>
    public Vector3 globalOffset = Vector3.zero;


    /// <summary>
    /// Local offset relative to target's rotation at which to look.
    /// </summary>
    public Vector3 localOffset = Vector3.zero;


    /// <summary>
    /// Up vector.
    /// </summary>
    public Vector3 up = Vector3.up;


    /// <summary>
    /// Whether or not we should use fixed update.
    /// </summary>
    public bool useFixedUpdate = false;

    #endregion


    #region Init

	/// <summary>
    /// 
    /// </summary>
    void Awake()
    {

    }


    /// <summary>
    /// 
    /// </summary>
    void Start()
    {

    }

    #endregion


    #region Update

    /// <summary>
    /// 
    /// </summary>
    void Update()
    {
        if (target == null) return;

        if (!useFixedUpdate)
            SharedUpdate(Time.deltaTime);
    }


    /// <summary>
    /// 
    /// </summary>
    void FixedUpdate()
    {
        if (target == null) return;

        if (useFixedUpdate)
            SharedUpdate(Time.fixedDeltaTime);
    }


    /// <summary>
    /// 
    /// </summary>
    /// <param name="step"></param>
    private void SharedUpdate(float step)
    {
        Vector3 t = target.Offset(localOffset, globalOffset);
        Quaternion tq = Quaternion.LookRotation(t - transform.position, up);

        // do linear motion
        transform.rotation = Quaternion.RotateTowards(transform.rotation, tq, linearLookRate * step);

        // do exponential motion
        float ex = 1.0f - Mathf.Pow(1.0f - exponentialLookRate, step);
        transform.rotation = Quaternion.Lerp(transform.rotation, tq, ex);
    }

    #endregion

}